﻿using System;

using XcoAppSpaces.Transport.Sockets.Auth.Contract;
#if NETFX_CORE
using TcpClient = Windows.Networking.Sockets.StreamSocket;
using EndPoint = Windows.Networking.HostName;
#else
using System.Net.Sockets;
#endif

namespace XcoAppSpaces.Transport.Sockets.Auth
{
	public class Authenticator : IAuthenticator
	{
		private ICheckIpBlacklist checkIpBlackList;
		private IDoHandshake doHandshake;
		private ICheckMultipleInvalidAttempts checkMultipleInvalidAttempts;

		internal Authenticator(ICheckIpBlacklist checkIpBlackList, IDoHandshake doHandshake, ICheckMultipleInvalidAttempts checkMultipleInvalidAttempts)
		{
			this.checkIpBlackList = checkIpBlackList;
			this.doHandshake = doHandshake;
			this.checkMultipleInvalidAttempts = checkMultipleInvalidAttempts;

			checkIpBlackList.Out_AllowedConnection += doHandshake.In_Connection;
			checkIpBlackList.Out_BlockedConnection += _ => this.Out_InvalidConnection(_);
			doHandshake.Out_AuthenticatedConnection += checkMultipleInvalidAttempts.In_ValidConnection;
			doHandshake.Out_AuthenticatedConnection += _ => this.Out_AuthenticatedConnection(_);
			doHandshake.Out_InvalidConnection += checkMultipleInvalidAttempts.In_SuspiciousConnection;
			doHandshake.Out_InvalidConnection += _ => this.Out_InvalidConnection(_);
			checkMultipleInvalidAttempts.Out_InvalidAddress += checkIpBlackList.In_InvalidAddress;
		}


		public void In_Connection(TcpClient tcpClient)
		{
			checkIpBlackList.In_Connection(tcpClient);
		}

		public event TcpClientHandler Out_AuthenticatedConnection;

        public event TcpClientHandler Out_InvalidConnection;

		
		public void Inject(SecuritySettings dependency)
		{
			doHandshake.Inject(dependency);
			checkMultipleInvalidAttempts.Inject(dependency);
		}

		public void Dispose()
		{
			checkMultipleInvalidAttempts.Dispose();
		}

		public static Authenticator CreateDefaultInstance()
		{
#if !SILVERLIGHT
			return new Authenticator(
				new CheckIpBlacklist(),
				new DoServerHandshake(new PrepareAuthentication(), new ReceiveGreeting(), new SendChallenge(), new ReceiveResponse(), new FinishAuthentication()),
				new CheckMultipleInvalidAttempts());
#else
			return new Authenticator(
				null,
				new DoServerHandshake(new PrepareAuthentication(), new ReceiveGreeting(), new SendChallenge(), new ReceiveResponse(), new FinishAuthentication()),
				null);
#endif
		}
	}
}
